package com.flyduck.vueshop.system.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyduck.vueshop.common.core.utils.BeanUtils;
import com.flyduck.vueshop.common.core.utils.StringUtils;
import com.flyduck.vueshop.common.mybatis.utils.PageUtils;
import com.flyduck.vueshop.system.admin.service.AdminRoleService;
import com.flyduck.vueshop.system.admin.vo.*;
import com.flyduck.vueshop.system.entity.SysRole;
import com.flyduck.vueshop.system.entity.SysRoleMenu;
import com.flyduck.vueshop.system.entity.SysUserRole;
import com.flyduck.vueshop.system.manager.SysPermissionCacheManager;
import com.flyduck.vueshop.system.mapper.SysRoleMapper;
import com.flyduck.vueshop.system.mapper.SysRoleMenuMapper;
import com.flyduck.vueshop.system.mapper.SysUserRoleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * SysRoleServiceImpl
 * </p>
 *
 * @author flyduck
 * @since 2024-06-03
 */
@Service
public class AdminRoleServiceImpl implements AdminRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Resource
    private SysPermissionCacheManager sysPermissionCacheManager;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Override
    public Page<AdminRoleRespVO> getRolePage(Page page, AdminRoleQueryReqVO adminRoleQueryReqVO) {
        Page<SysRole> sysRolePage = sysRoleMapper.selectPage(page,
                new LambdaQueryWrapper<SysRole>()
                        .like(StringUtils.isNotBlank(adminRoleQueryReqVO.getName()), SysRole::getName, adminRoleQueryReqVO.getName())
                        .orderByDesc(SysRole::getCreated)
        );

        return PageUtils.convert(sysRolePage, AdminRoleRespVO.class);
    }

    @Override
    public AdminRoleDetailsRespVO getRoleDetailsById(Long id) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        AdminRoleDetailsRespVO adminRoleDetailsRespVO = BeanUtils.toBean(sysRole, AdminRoleDetailsRespVO.class);

        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(
                new LambdaQueryWrapper<SysRoleMenu>()
                        .eq(SysRoleMenu::getRoleId, id)
        );
        List<Long> menuIds = sysRoleMenuList.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());
        adminRoleDetailsRespVO.setMenuIds(menuIds);

        return adminRoleDetailsRespVO;
    }

    @Override
    public void saveRole(AdminRoleSaveReqVO adminRoleSaveReqVO) {
        SysRole sysRole = BeanUtils.toBean(adminRoleSaveReqVO, SysRole.class);
        sysRole.setCreated(LocalDateTime.now());
        sysRoleMapper.insert(sysRole);
    }

    @Override
    public void updateRole(AdminRoleUpdateReqVO adminRoleUpdateReqVO) {
        SysRole sysRole = BeanUtils.toBean(adminRoleUpdateReqVO, SysRole.class);
        sysRole.setUpdated(LocalDateTime.now());
        sysRoleMapper.updateById(sysRole);

        //删除角色关联用户的所有权限
        sysPermissionCacheManager.clearPermissionListByRoleId(adminRoleUpdateReqVO.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchDeleteByIds(List<Long> ids) {
        //删除角色关联表
        sysUserRoleMapper.delete(
                new LambdaQueryWrapper<SysUserRole>()
                        .in(SysUserRole::getRoleId,ids)

        );
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>()
                        .in(SysRoleMenu::getRoleId,ids)
        );

        //删除角色关联用户的所有权限
        ids.stream().forEach(id -> {
            sysPermissionCacheManager.clearPermissionListByRoleId(id);
        });

        sysRoleMapper.deleteBatchIds(ids);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void assignMenuListToRole(Long roleId, List<Long> menuIds) {
        //先删除之前的
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>()
                        .eq(SysRoleMenu::getRoleId,roleId)
        );

        //保存新的关系
        List<SysRoleMenu> sysRoleMenuList = menuIds.stream()
                .map(menuId -> {
                    SysRoleMenu sysRoleMenu = new SysRoleMenu();
                    sysRoleMenu.setRoleId(roleId);
                    sysRoleMenu.setMenuId(menuId);
                    return sysRoleMenu;
                }).collect(Collectors.toList());
        sysRoleMenuMapper.insertBatch(sysRoleMenuList);

        //删除相关的缓存信息
        sysPermissionCacheManager.clearPermissionListByRoleId(roleId);
    }
}
